PHP


一、服务器知识

1 基础知识

基础知识:

其他知识:

  • C/S(胖客户端),B/S(瘦客户端)
  • PWA:Progressive web app
  • 浏览器 flash 默认关闭。
  • 服务端技术:CGI,PHP,ASP,JSP,ASP.NET
  • MIME(多用途网际邮件扩充协议):是一种标准,用来表示文档、文件或字节流的性质和格式。 MIME

WAMP是指: Windows + Apache + Mysql + PHP

LAMP是指:Linux + Apache + Mysql + PHP

传统内核 对应浏览器 新内核
Trident IE
T+W(双核) 搜狗,360,遨游
Webkit Safari
Webkit Chrome Blink(微信小程序内核)
Presto Opera Blink
Gecko Firefox Servo

2 服务器搭建

  1. 购买服务器:
  2. 远程连接:
  3. 下载宝塔:

二、PHP语言基础

official::PHP: Hypertext Preprocessor

1 定义

PHP是一种运行在服务器端的脚本语言,可以嵌入到 HTML 中。

标记方式(前两种基本弃用,开启:php.ini——short_open_tag / asp_tags):

  • ASP标记:<% code %>
  • 短标记:<? code ?>(“<?=”是PHP的一个短的开放式标签,是echo() 的快捷用法。)
  • 脚本标记:<script language="php">code</script>
  • 标准标记(常用):<?php code ?>

注释:

  • 行注释:// #
  • 块注释:/ /

语句间用 ;隔开,?>会自带所以最后一个语句可以不写。

注:<?php code ?>使用时可以不写 ?>,这样后面的空行都会解析成php而不是html,从而节约行数。

2 变量与常量

// 定义
$var;
// 赋值
$var = 1;
// 删除
unset($var);

// 超全局变量:系统定义的变量(如:预定义变量)
// 预定义变量:提前定义的变量,系统定义的变量,存储许多需要用到的数据(预定义变量都是数组)。
$_GET // 获取所有以 get 方式提交的数据的表单
$_POST // 获取 post 提交的数据
$_REQUEST // get、post和cookie的(重名不同服务器处理情况不同,一般不用)
$GLOBALS // PHP中所有的全局变量
$_SERVSER // 服务器信息
$_SESSION // session 会话数据
$_COOKIE // cookie 会话数据
$_ENV // 环境信息
$_FILES // 用户上传的文件信息

// 有趣案例
$a = 'b'; $b = 'abc'; echo $$a == 'abc';

// 常量(不要$,否则会认为成变量)
//1、可以定义特殊字符,例:define( "-_-" , "smile" ),参数三表示对大小写敏感,默认 false 不敏感
define("name",value[,false]);
//2、5.3之后才有
const name = value;

// 系统常量
PHP_VERSION // PHP版本号。
PHP_INT_SIZE // 整形大小。
PHP_INT_MAX // 整形能表示的最大值。

// 魔术常量:随环境变化,用户无法改变。
__DIR__ // 当前被执行的脚本所在电脑的绝对路径。
__FILE__ // 当前被执行的脚本所在电脑的绝对路径。(带自己文件的名字)
__LINE__ // 当前所属的行数。
__NAMESPACE__ // 当前所属的命名空间。
__CLASS__ // 当前所属的类。
__METHOD__ // 当前所属的方法。
__FUNCTION__ // 当前函数名字

3 内存

区域:

  • 栈区:程序可以操作的内存部分(不存数据,运行程序代码),少但是快。
  • 代码段:存储程序的内存部分(不执行)。
  • 数据段:存储普通数据(全局区和静态区)。
  • 堆区:存储复杂数据,大但是效率低。

传递:

  • 值传递:$a = $b ; ,在数据段重新生成数据。
  • 引用传递:$a = &$b; ,地址传递。

4 文件包含

在一个PHP脚本中去将另一个文件的执行结果包含进来。

文件包含的意义:

  1. 要么使用被包含文件中的内容,实现代码的共享(重用):向上包含(索要,在当前脚本要用某个代码之前包含别的文件)

  2. 要么自己有东西可以给别的文件使用,实现代码的共享(重用):向下包含(给予,在自己有某个东西的时候,需要别的脚本来显示(自己代码写完之后包含其他文件)

  3. 最大的作用:分工协作,每个脚本做的事情不一样,因此可以使用协作方式,让多个脚本共同完成一件事情。

在PHP中文件的包含有四种形式:(两种大形式)

  • lnclude():包含文件。
  • Include_once():系统会自动判断文件包含过程中,是否已经包含过(一个文件最多被包含一次)。
  • Require():与include相同
  • Require_once():与include_once相同

包含代码:Include 'file'或Include('file');

Include与Require:本质一样,但Include报错是Warning,不影响后面可执行代码的执行;而Require报错是Fatal error,后面语句将不会执行。

PHP代码的执行流程:

  1. 读取代码文件。(PHP程序)
  2. 编译:将PHP代码转换成字节码。(生成opcode)
  3. zendengine来解析opcode,按照字节码去进行逻辑运算。
  4. 转换成对应的HTML代码。

文件加载原理:

  1. 在文件加载( include 或者require〉的时候,系统会自动的将被包含文件中的代码相当于嵌入到当前文件中
  2. 加载位置:在哪加载,对应的文件中的代码嵌入的位置就是对应的include位置
  3. 在PHP中被包含的文件是单独进行编译的。

PHP文件在编译的过程中如果出现了语法错误,那么会失败〈不会执行);但是如果被包含文件有错误的时候,系统会在执行到包含include这条语句的时候才会报错。

注意路径:相对路径指的是当前执行文件下的路径(多次包含文件时可能会失效),可以用"file/file.php"而非"./file/file.php"

5 数据类型

PHP是一种弱类型语言,变量本身没有数据类型。

区分:三大类八小类。

简单(基本)数据类型:4个小类:

  • 整型:int/integer,系统分配4个字节存储,表示整数类型(有前提)
  • 浮点型:float/double,系统分配8个字节存储,表示小数或者整型存不下的整数
  • 字符串型: string,系统根据实际长度分配,表示字符串(引号)
  • 布尔类型:bool/boolean,表示布然类型,只有两个值: true和 false

复合数据类型:2个小类:

  • 对象类型:object,存放对象(面向对象)
  • 数组类型: array,存储多个数据(一次性)

特殊数据类型:2个小类:

  • 资源类型:resource,存放资源数据(PHP外部数据,如数据库、文件)
  • 空类型:NULL,只有一个值就是NULL(不能运算)

类型转化方式:自动转化,手动转化:(int)$a

字符串转数字:

  1. 以字母开头的字符串,永远为0
  2. 以数字开头的字符串,取到碰到字符串为止(不会同时包含两个小数点)
// 类型判断
is_type( $name );
// 类型查看
var_dump( $one , $two , ... );
// 获得类型,返回的是字符串
Gettype( $name );
// 转化类型。
Settype( $name , type );


// 八进制:0num(输出时系统会自动转化成十进制),其他同C。
// bin:二,oct:八,dec:十,hex:十六。
Decbin(); //十转二
Bindec(); //二转十

// 判断数为空
Empty();
// 判断数存在
Isset();

6 运算符

运算符大部分同理c语言

// 数值判断
== / !=
// 数值和类型判断
=== / !==

// 连接运算符
$a = $a.$b;
// 上面字符串$a$b拼接后赋值给$a,也可以写成下面
$a .= $b;

// 错误抑制符:在语句前加 @ ,出错将不会报错
@if(0/0);

7 输入输出

// 输出一个或多个语句或变量。(不能输出bool判断,数组,类等)
echo "html",str,...;
// 特殊常量的输出。(例:"-_-")
echo constant( "str" );

// 显示数值,可用于类。
print_r(obj);

// 显示数值和类型。
var_dump(obj);

8 判断

同C

endif,endswitch

// 一定要用三等于,否则找到位置为0时一样是false。
if(strpos('abc','a') === false)
{ echo '没有找到';}

9 循环

同C

endwhile(没有dowhile),endforeach

为了美观可以把 for的:

  • “{“ 替换成 “:”
  • “}” 替换成 “endfor”
// 下面两者等价
for( ;; ) {}
for( ;; ): endfor

// foreach 遍历值
foreach( $arr as $v )
foreach( $arr as $k => $v )

10 字符串

单双引号:

  • 单引号:不解释,直接输出。
  • 双引号:变量解释后输出。

结构化字符串:

  • 会保持原有结构,所有东西都是字符串。(要识别变量应当加引号)

  • 如:"$a"

// limit:边界符,首尾应当一致,首尾后不跟东西,尾必须顶格。
// nowdoc字符串:没有单引号的单引号字符串。
$str = <<< "limit"
...
limit;

// heredoc字符串:没有双引号的双引号字符串。
$str = <<< limit
str
limit;
// 字符串长度
strlen();
// 扩展(去除分号)
extension = php_mbstring.dll;
// 按字符编码计算字符串长度
mb_strlen($str,[ encoding ]);

// 字符串函数
// 将数组中的元素按照某个规则连接成一个字符串。
lmplode(exp,$arr);
// 将字符串按照某个格式进行分割,变成数组。
Explode($c,$str);
//按照指定长度拆分字符串得到数组
Str_split($str,len);

// 去除两边指定字符(还有 Ltrim,Rtrim)
Trim($str,[,$c]);
// 指定位置开始截取字符串,可以截取指定长度。(不指定到最后)
Substr($str,start[,len]);
// 从指定位置开始,输出 c 在 str 出现的一个位置后面的字符串
Strstr($str,$c);

// 全部小写
Strtolower($str$str);
// 全部大写
Strtoupper($str);
// 首字母大写
uctirst($str);

// find在str中首次出现的位置,起始位置0
strpos($str,find,[start]);
// 查找find在str最后一次出现的位置
strrpos($str,find,[start]);
//(以下查找不区分大小写)
// 查找find在str首次出现的位置
stripos($str,find,[start]);
// 查找find在str最后一次出现的位置
strripos($str,find,[start]);


// 将str中的find替换成replace,可替换count处
str_replace(find,replace,$str,[&count]);
// 不区分大小写
str_ireplace(find,replace,$str,[&count]);

// 格式化输出(同c)
printf("%d",num);
// 把格式化的字符串写入变量中
$info = 'age:%d';
sprintf($info,num);

// 重复某个字符串N次
Str_repeat($str,N);
// 随机打乱字符串
Str_shuffle();

// 把str中对应字符转换为 HTML 实体
htmlentities($str);
// 剥去str中的 HTML 标签
strip_tags($str);

// 在预定义字符之前添加反斜杠
addslashes($str);
// 删除由 addslashes() 函数添加的反斜杠
stripslashes($str);

11 数组

不填下标默认从最大数字下标向后加。

下标所有都是整数:索引数组。

下标所有都是字符串:关联数组。

下标混合:混合数组。

true,false,null 自动变成 1,0,” “。

// 定义数组(类似 js)
$name = array( elem1 , elem2 , ... );
$name = [ elem1 , elem2 , ... ];
$name[] = value1;
$name[ index ] = value;
// 定义关联数组
$name = array( 'index' => 'value' , ... )

// 下标不动,顺序/逆序排序
sort($arr); / rsort($arr);
// 下标跟随,顺序/逆序排序
asort($arr); / arsort($arr);
// 按键名排序
ksort($arr); / krsort($arr);
// 随机打乱
shuffle($arr);
// 指针置首/尾
reset($arr); / end($arr);
// 指针下移/上移并返回上一/下一元素值
next($arr); / prev($arr);
// 获得当前元素值/键
current($arr); / key($arr);
// 注意:指针移动超过数组后不能用 next 和 prev 调整指针位置,要用 reset 和 end。

// 数组长
count($arr);
// 最大最小
max($arr);min($arr);
// 往数组中加入一个元素(数组后面)
array_push(array &$array,mixed $var[, mixed $... ]);
// 从数组中取出一个元素(数组后面)
array_pop($arr);
// 从数组中加入一个元素(数组前面)
array_unshift(array &$array,mixed $var[, mixed $... ]);
// 从数组中取出一个元素(数组前面)
array_shift($arr);


// 统计所有元素的和
array_sum($arr);
// 统计数组中所有值出现的个数
array_count_values($arr);
// 数组元素逆转
array_reverse($arr);
// 把一个或多个数组合并为一个数组
array_merge($arr1,[,$arr2]);

// 判断arr中是否存在指定的key
array_key_exists(key,$arr);
// 判断str值在arr中,type是否需要类型相同
in_array($str,$arr,type);
// 搜某个value,返回key
array_search($str,$arr);

// 去重
array_unique($arr);

// 获取一个数组的所有下标,返回一个索引数组
array_keys($arr);
// 获取一个数组的所有值,返回一个索引数组
array_values($arr);

12 函数

12.1 自定义函数

同C++:默认值。

不同C:函数定义可以放在函数执行之后,因为他会先编译再执行,编译时代码段已经有了函数。

// 定义函数
function name(){ return; }


//函数中使用全局变量(不存在会直接生成)
global $name;
//可以有闭包,匿名函数。(use是将外部变量保留传递给内部用)
$fun = function() use($name){}

12.2 输出

// 输出,本质是结构不是函数,返回1,可以不用括号。
print();
// 只输出值。
print_r();
// 输出值和类型。
var_dump();

12.3 时间

date()

// 日期(参数一填格式化输出, y m d h i s分别表示年月日时分秒,后一个表示时间戳,默认当前)
date(format,[time()]);
date('Y-m-d H:i:s');
date('Y-m-d',1462686882);
// 时间戳
time();
// 时间戳,微秒级
microtime();
// 正确的输入的英文格式都能转化成时间戳
strtotime('str');

12.4 数学

max();
min();
pow();
abs();
sqrt();

// 指定区间的随机整数
rand([min],max);
// 同rand(),效率比rand()高
mt_rand();
// 四舍五入
round();
// 上取整
ceil();
// 下取整
floor();

// 转化 整形/浮点/字符串
intval($var);
floatval($var);
strval($var);

12.5 函数参数

// 检测函数名字是否存在
function_exists(func);

// 函数内使用
// 获得函数第 num 个参数
func_get_arg( num );
// 获得函数全部参数
func_get_args();
// 获得函数参数
func_num_args();

12.6 检验函数

// 检验$var是否定义。已定义检测是否不为NULL
isset($var);
// 检测是否为空
// 1.未定义
// 2.值是否为0
empty($var);

// 判断是否是*
is_*();
// string/int/float/bool/null/array
is_int();
is_numeric(); // 是否是数字

12.7 正则表达式

# 首个匹配则终止($pattern="/ exp /":双斜杠中写表达式)
preg_match(string $pattern,obj);
# 匹配所有
preg_match_all(string $pattern,obj);

# 判断输入的是数字
preg_match_all("/^\d+$/",$num)

13 文件

13.1 文件读写

// 打开文件(方式rwax,+,b)(x是只写,w是写入)
// http只能只读,ftp只能只读或只写
$file = fopen("https://www.baidu.com/","r");
$file = fopen("ftp://user:password@en.cn/exam.txt","w");
$file = fopen("/home/file.txt","wb");

//关闭文件
fclose($file);

// 读取文件
// 读取整个文件,指定长度
string fread(resource handle,int length);
// 一行字符,读到回车或length-1就返回
string fgets(resource handle[,int length]);
// 一行字符并去掉所有html和php标记
string fgetss(resource handle[,int length]);
// 一个字符
string fgetc(resource handle);
// 无需开关文件就可读
string file_get_contents(resource handle);
// 文件读入数组,每个元素对应一行
array file(resource handle);
// 读到缓冲,返回读取字符数
int readfile(resource handle);

// 文件指针操作
// 移动到开头
bool rewind(resource handle);
// 返回当前位置
int ftell(resource handle);
// 移动到指定位置(移动偏移量,未指定起始位置默认从文件开头开始)
int fseek(resource handle,int offset[,int origin]);
// origin取值:SEEK_SET(0):文件开头,SEEK_CUR(1):当前位置,SEEK_END(2):文件末尾

// 写入文件
// 写入字符串(设置了长度会只写入length个字符)
int fwrite(resource handle,stirng stirng[,int length]);
// 无需开文件就可以写(mode指定方式,FILE_APPEND:追加)
int file_put_contents(string filename,string data[,int mode]);

13.2 文件操作

// 文件操作
// 复制
copy(src,dest);
// 删除
unlink(dest);
// 重命名
rename(old,new);
// 文件截断
ftruncate(src,length);
// 判断文件或文件夹存在
file_exists(dest);
// 判断路径存在且为文件
is_file(name);

// 文件属性
// 文件大小
$fsize = filesize(file);
// 文件类型
filetype(file);
// 时间戳
date('Y-m-d H:i:s',filectime(file));
// 修改时间
filemtime(file);
// 访问时间
fileatime(file);
// 物理路径
realpath(file);
// 数组形式返回路径和文件名信息
pathinfo(file);
// 相对当前文件的路径信息
dirname(file);
// 文件名信息
basename(file);
// 数组形式返回大部分属性值
stat(file);

// 路径操作
// 新建目录
mkdir(pathname);
// 删除目录
rmdir(dirname);
// 取得当前文件所在目录
getcwd(void);
// 改变当前目录
chdir(dirname);
// 打开目录,返回目录指针
opendir(path);
// 关闭目录,参数为目录指针
closedir(*p);
// 遍历目录
readdir();
// 数组形式遍历目录,sort设置为True或False
scandir(path,sort);
// 目录指针重置回目录开头
rewinddir(*p);

13 类与对象

# 大体同c++:private,public,$this->
# 定义类
class name
{
var $para;
function name(){};
}

# 构造函数
function __construct(){};
# 析构函数
function __destruct(){};

# 初始化对象
$name = new calss_name();
# 访问对象
$name->para;
$name->function_name();

# 静态变量常量访问
$name::function_name();
# 检测某个对象是否属于某个类
echo $name instanceof class_name;
# 继承
class name extends father{};

# 多态
class Students{};
class jk extends Students{};
class xxs extends Students{};

14 错误

错误代号:

  • 所有看到的错误代码在PHP中都被定义成了系统常量。(可以直接使用)

  • 所有以E开头的错误常量(代号)其实都是由一个字节存储,然后每一种错误占据一个对应的位,如果想进行一些错误的控制,可以使用位运算进行操作。

错误类型:

  1. 系统错误:系统内置的错误。
  2. 用户错误:用户在使用自定义错误触发的时候,会使用到的错误代号。(系统不会用到)
  3. 其他错误

错误显示设置:哪些错误该显示,以及该如何显示。

在PHP中,其实有两种方式来设置当前脚本的错误处理:

  1. PHP的配置文件:

    • php.ini文件:全局配置。
    • Display_errors:是否显示错误。
    • Error_reporting:显示什么级别的错测。
    • error_log:错误日志路径。(log_errors:开启错误日志)
  2. 可以在运行的PHP脚本中去设置:(级别比配置文件高)

    • Error_reporting():设置对应的错误显示级别。(没有参数表示当前错误级别)

    • lniset('配置文件中的配置项',配置值);

    • lni_set('error..reporting',E_ALL);
    • lni_set('display_errors',1);
系统错误 错误效果
E_PARSE 编译错误,代码不会执行
E_ERROR fatal error,致命错误,会导致代码不能正确继续执行(出错的位置断掉)
E_WARNING warning,警告错误,不会影响代码执行,但是可能得到意想不到的结果
E_NOTICE notice,通知错误,不会影响代码执行
用户错误 错误效果
E_USER_ERROR fatal error
E_USER_WARNING warning
E_USER_NOTICE notice
其他错误 错误效果
E_ALL 代表着所有从错误(通常在进行错误控制的时候使用比较多),建议在开发过程中(开发环境)使用。
// 排除通知级别notice
E_ALL & ~E_NOTICE

//只要警告和通知
E_WARNING | E_NOTICE
// 抛出错误('str':错误提示,error:抛出错误类型(默认notice))
trigger_error('str',[error]);
// 设置错误(func:错误执行函数,error:触发错误)
set_error_handler(error_func,[error]);
// 错误函数(错误类型,错误提示,错误文件位置,错误行,错误文本)
function error_func($errno,$errstr,[$errfile,$errline, $errcontext])
{
if( !( error_reporting() & $errno )) // 当前错误在系统中不存在,无法处理。
return false;
}

15 伪类型

实际不存在的类型,便于学习:

  • Mixed:混合类型。
  • Number:数值类型。

三、PHP动态交互

1 Web交互编程

1.1 收发数据

// 获得post数据
$_GET['name'];
$_POST['name'];

// 返回当前执行脚本的文件名
$_SERVER['PHP_SELF'];
// 返回访问页面使用的请求方法(例如 POST)
$_SERVER['REQUEST_METHOD'];
// 返回当前执行脚本的文件名
$_SERVER['PHP_SELF'];
// 返回浏览当前页面的用户的主机名
$_SERVER['REMOTE_HOST'];
// 返回访问者浏览器信息
$_SERVER['HTTP_USER_AGENT'];
// 返回传递的cookie信息
$_SERVER['HTTP_COOKIE'];

// 客户端与服务器握手IP,如果使用代理则会获取到代理IP
$_SERVER['REMOTE_ADDR'];
// 代理服务器发送的HTTP头(可伪造)
$_SERVER['HTTP_CLIENT_IP'];
// 用户是在哪个IP使用的代理(可伪造)
$_SERVER['HTTP_X_FORWARDED_FOR'];

// 获得环境变量
getenv('REMOTE_ADDR');

// @的使用
@$_GET['c'];
/*
@会抑制错误消息的输出。表达式前若加上@,表达式出现错误则返回false。
在此处若无@且Get中不存在参数c时则会返回一个未定义变量,有@且Get中不存在参数c返回null*/

1.2 header()

# header()是向浏览器传一个HTTP响应头信息
void header(stringmessage[, bool replace[, int http_response_code]])
# stringmessage格式:header_name:header_value


# 案例
# 1.重定向网页
<?php
$url='http://web.3eol.com.cn';
header("Location:$url");
?>

# 2.延迟转向
<?php
//3秒后,跳转到微博
header('refresh:3;url=http://weibo.com');
?>

# 3.设置中文
header('Content-type:text/html;charset=utf-8;');

# 4.强制下载文件
<?php
$filename='test.gif';
header('Content-type:image/gif');
header('Content-Disposition:attachment; filename="'.$filename.'"');
header('Content-Length:'.filesize($filename));
?>

1.3 缓冲发送

没开启缓冲区时,程序执行输出的内容都是直接输出到浏览器的。

开启后,程序执行输出的内容会先存入缓冲区,之后再根据后续代码或脚本执行完成再发送给浏览器。

# 打开输出缓冲区
ob_start();
# 返回内部缓冲区的内容
$out = ob_get_contents();
# 返回内部缓冲区的内容,并关闭缓冲区
$out = ob_get_clean();
# 返回内部缓冲区的内容,并关闭缓冲区,再把缓冲区内容立刻输出到客户端
$out = ob_get_flush();
# 返回内部缓冲区的长度
$len = ob_get_length();
# 删除内部缓冲区的内容,但不关闭缓冲区
ob_clean();
# 立刻输出内部缓冲区的内容,且不关闭缓冲区
ob_flush();
# 刷新输出缓冲,将ob_flush输出的内容,以及不在PHP缓冲区的内容全部输出至浏览器
flush();
# 删除内部缓冲区的内容,并关闭缓冲区
ob_end_clean();
# 立刻输出内部缓冲区的内容,且不关闭缓冲区
ob_end_flush();

2 获得缓存

cookie是小文本文件。

小是防止服务器写入巨大的垃圾信息给客户端。

文本文件是指文件不可执行,防止服务器写入恶意代码给客户端。

cookie安全:cookie修改 伪造 盗取

获取来访者IP的方法

// 设置cookie(cookie名,cookie值,过期时间,有效目录,有效域名,是否HTTPS,是否只可http)
setcookie(name, value, expire, path, domain,secure,httponly);
setcookie('sex','女',time()+60,'','',falsefalse)
# httponly设置为true,则意味着该cookie只能通过HTTP协议来访问,如果httponly设置为false或省略,则该cookie可以被客户端脚本访问,这样易被XSS攻击。

// 设置案例
setcookie('username','admin'); // 会话型cookie,浏览器关闭即删除
setcookie('username','admin',time()+60); // 长效型cookie,有效期为60秒
setcookie('username','admin',time()+24*60*60); // 长效型cookie,有效期为1天
setcookie("user", "", time()-3600); // 删除cookie

2.2 Session

Session 用于存储用户的信息。存储于 Session 中的变量持有单一用户的信息,并且对于一个应用程序中的所有页面都是可用的,用session_id来标识每一个会话。

注意事项:

  1. session_start()函数前面不能有任何代码输出到浏览器,最好加在页面头部,或先用ob_start()函数打开输出缓冲区。
  2. 对一个不存在的Session变量赋值,将自动创建该变量。已存在则修改值。
  3. 如果新打开一个浏览器访问同一网页则无法获得Session信息。因为新开一个浏览器相当于一个新的用户在访问。
  4. 只要创建了Session变量,该Session变量就能被网站中的所有页面访问。

有效期:默认24分钟(1440秒)

修改session有效期:

  1. 修改php.ini中的默认值,session.gc_maxlifetime=1440;
  2. 使用ini_set()方法修改session有效期

session安全:会话劫持(session劫持,在PHPSESSID有效期内使用)

// session使用
session_start(); // 开启session
$_SESSION['session_name']=''; // 设置或获得session
// session_unset()只能删除$_SESSION数组中所有元素,不删除保存文件。session_destroy()只删文件不删数组元素,所以可以配合使用
session_unset();
session_destroy();
header("location:main.php");

// session设置
ini_set('session.save_path','/tmp/'); // 设置保存路径
ini_set('session.gc_maxlifetime',60); // 保存1min
setcookie(session_name(),session_id(),time()+60,"/"); // 设置会话Cookie的过期时间

2.3 区别

  1. Cookie限制大小,每个文件不超过4KB,每个站点最多设置20个Cookie。(不同浏览器可能不同)
  2. Session 仍然要通过 Cookie 实现,因为用户的 Session ID 必须保存在会话的 Cookie 中。
相似点 Session Cookie
功能 存储和跟踪特定用户的信息 存储和跟踪特定用户的信息
优势 在整个网站的所有页面都可以访问 在整个网站的所有页面都可以访问
不同点 Session Cookie
建立方式 每次访问网页时会自动建立Session对象 需要通过代码建立
存储位置 服务器端 客户端
应用场合 记住正在访问的用户信息 记住曾经访问过的用户信息

3 文件上传

如果表单中有文件上传域,则定义表单时必须设置 enctype="multipart/form-data",method=post

如果要限制上传文件的大小,可以在表单中添加一个隐藏域:<input type="hidden" name="MAX_FILE_SIZE" value="10240">。该隐藏域必须放在文件上传域的前面,否则设置会失效。

// 获取上传文件的信息
// 文件名(不包括路径)
$_FILES['upfile']['name'];
// MIME类型,如image/gif
$_FILES['upfile']['type'];
// 文件大小,单位是B
$_FILES['upfile']['size'];
// 上传文件在服务器的临时名(包括路径)
$_FILES['upfile']['tmp_name'];
// 上传文件的错误号,整数,错误号如下
$_FILES['upfile']['error'];

// 移动文件
// 该函数还会额外确认第一参数上传的文件是否合法
move_uploaded_file(old,new)
old:$_FILES['file']['tmp_name'];

// 多文件上传和获得
// 上传
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="upfile[]" />
<input type="file" name="upfile[]" />
<input type="submit" value="up file" />
</form>
// 获得
$_FILES['upfile']['name'][0]
错误号 说明
0 文件上传成功,没有错误发生
1 上传文件的大小超过了 php.ini 中 upload_max_filesize 选项限定的值
2 上传文件大小超过了表单隐藏域中 MAX_FILE_SIZE 选项指定的值
3 只上传了部分文件,如上传过程中网络中断
4 没有上传的文件,如没有选择上传文件就直接单击“上传”按钮
6 找不到临时文件夹
7 服务器上临时文件写入失败,通常是权限不够
8 上传的文件被PHP扩展程序中断

4 访问数据库

4.1 MySQL数据库

路径:http://127.0.0.1/phpMyAdmin

默认账号密码:root——root

4.2 PDO函数

// 连接数据库,初始化pdo
$dsn="mysql:host=localhost;dbname=guestbook";
$db=new PDO($dsn,$db_username,$db_password);
// 数据库连接默认不是长连接,长连接则需要如下设置
$db=new PDO($dsn,$db_username,$db_password,array(PDO::ATTR_PERSISTENT=>true));

// PDO对象的方法
// 执行一条有结果集返回的sql语句,返回结果集PDOStatement对象
$res = $pdo->query($sql);
// 执行一条sql语句,返回所影响的记录数
$res = $pdo->exec($sql);
// 获取最近一条插入到表中记录的自增的ID值
$pdo->lastInsertId();
// 准备要执行的sql,用于执行存储过程等
$res = $pdo->prepare($sql);

// PDOStatement对象的方法(PDO执行结果的返回结果为PDOStatement)
// Mode:PDO::FETCH_ASSOC(关联数组)
// 返回当前指针指向记录并把指针移向下一行,到结果集尾则返回false
$res->fetch([$Mode]);
// 返回赋有所有行的二维数组,指针指向结果集尾
$res->fetchAll([$Mode]);
// 返回结果集中下一行某列的值
$res->fetchColumn();
// 设置fetch()或fetchAll()方法结果返回模式,如关联数组、索引数组等
$res->setFetchMode($Mode);
// 返回结果集的记录总数,仅对query()和prepare()有效
$res->rowCount();
// 返回结果集列总数
$res->columnCount();
// 将一个列和一个指定的变量名绑定(必须设置fetch()方法为FETCH_BOTH)
$res->bindColumn();
// 执行准备好的sql语句,可以对准备的语句中的参数用索引数组赋值,如$para_arr= array(':title'=>'标题',...)
$res->execute([$para_arr]);

// 抛出PDO异常
throw new PDOException('tip');
// 关闭连接
$db->close();

4.3 防止sql注入查询

// 1.占位符占位(任意选一种)
$sql = "insert into lyb(title,content,author) values(?,?,?)";
$sql = "insert into lyb(title,content,author) values(:title,:content,:author)";
// 2.准备
$stmt = $db->prepare($sql);
// 3.绑定参数
$stmt = $db->bindParam(1,$title); //绑定第一个?
$stmt = $db->bindParam(':title',$title);
// 按类型绑定?占位,i:int,d:double,s:string,b:bool。
$stmt = $db->bindParam('sss',$title,$content,$author);
// 4.执行
$stmt->execute();
// 也可以在查询时直接绑定(一次性绑定所有参数)
$stmt->execute(array('POD预处理','插入记录',"西贝乐"));
// 5.获得结果
$res = $stmt->get_result();
// 6.处理每一行数据
while ($row = $result->fetch_assoc()) {}

4.4 PDO流程案例

// PDO
// PDO的安装,php5.1以上默认安装PDO
;extension=php_pdo.dll // 去掉注释打开,之后选择下面链接的数据库。(文件中也可能没有)
;extension=php_pdo_mysql.dll // mysql
;extension=php_pdo_mssql.dll // SQL Server
;extension=php_pdo_oci.dll // Oracle
;extension=php_pdo_obdc.dll // OBDC,访问微软数据库可以用ODBC


// 初始化PDO
try
{
$dsn="mysql:host=localhost;dbname=guestbook";
$db=new PDO($dsn,$db_username,$db_password);
$db->query("set names utf8"); //设置字符编码
//设置PDO错误警告模式,用于调试
//$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
}
catch( PDOException $e)
{
echo "error:". $e->getMessage() . '<br>';
exit();
}

// 执行操作
$list=$res->fetchAll(PDO::FETCH_ASSOC);
foreach ($list as $key => $value) {
echo '用户名:'.$value['username'].',昵称:'.$value['nickname'].'<br>';
}

// 释放资源
$res=null;
$db=null;

4.5 PDO事务操作

// 开启事务,关闭自动提交模式
$db->beginTransaction();
// 提交事务,然后回到自动提交模式
$db->commit();
// 回滚事务
$db->rollBack();
// 检查是否在一个事务内,如果当前事务处于激活状态则返回true
$db->inTransaction();

4.6 PDO事务案例

<?php
try
{
$dsn="mysql:host=localhost;dbname=guestbook";
$option=array(PDO::ATTR_AUTOCOMMIT,0);
$db=new PDO($dsn,'root','root',$options);
$db->query('set names utf8');
}
catch( PDOException $e)
{
echo "error:". $e->getMessage() . '<br>';
exit();
}
try
{
$db->beginTransaction();
var_dump($db->inTransaction()); // 激活返回true
$sql="update lyb set sex='female' where sex='2'";
$res_1 = $db->exec($sql);
if($res_1 == 0)
{
throw new PDOExecption('update sex failed!');
}
$res_2 = $db->exec("update lyb set title='teacher' where title like '%ab%'");
if($res_2 == 0)
{
throw new PDOExecption('update sex title!');
}
$db->commit();
}
catch(PDOException $e)
{
$db->rollBack();
echo $e->getMessage();
}
?>

5 cURL

cURL 函数

curl_setopt函数

// cURL流程
// 创建一个cURL资源
$ch = curl_init();

// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, "http://www.w3cschool.cc/");
curl_setopt($ch, CURLOPT_HEADER, 0);

// 抓取URL并把它传递给浏览器
curl_exec($ch);

// 关闭cURL资源,并且释放系统资源
curl_close($ch);


// cURL多线程函数
$mh = curl_multi_init(); // 返回一个新的cURL多线程句柄
curl_multi_add_handle($mh, $ch); // 将单个 cURL 句柄添加到多线程句柄中,$mh 为多线程句柄,$ch 为 cURL 句柄
curl_multi_exec($mh, $running); // 执行一组cURL 句柄
curl_multi_getcontent($ch); // 获取单个cURL句柄的内容,$ch 为 cURL 句柄
curl_multi_remove_handle($mh, $ch); // 从多线程句柄中移除单个cURL句柄,$mh为多线程句柄,$ch为cURL句柄
curl_multi_close($mh); // 关闭多线程句柄,$mh为多线程句柄
curl_getinfo($ch, $option); // 获取cURL句柄的信息,$ch为cURL 句柄,$option 为信息选项
// 多线程同时访问网页,结果保存到$res中

<?
$connomains = array( // 设置请求的url
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/"
);
$mh = curl_multi_init();
foreach($connomains as $i => $url){
$conn[$i] = curl_init($url);
curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1); // 不添加输出内容
curl_multi_add_handle($mh, $conn[$i]); // 添加cURL资源句柄
}
do{ $n = curl_multi_exec($mh, $active); }
while($active);
foreach($connomains as $i => $url){
$res[$i] = curl_multi_getcontent($coon[$i]); // 将获取的内容保存在数组元素中
curl_close($conn[$i]); // 循环关闭每个cURL请求
}
print_r($res); // 输出获取的内容
// cURL检测网页是否正常

if($mhinfo = curl_multi_info_read($mh)){ // 如果获取网页成功
$chinfo = curl_getinfo($mhinfo['handle']); // 获取网页执行的信息
if(!$chinfo['http_code']){ // 如果http_code为空
$dead_urls[] = $chinfo['url']; } // 将url保存到死链的数组中
else if(!$chinfo['http_code'] == 404){ // 404
$notfound_urls[] = $chinfo['url']; } // 将url保存到找不到的数组中
else{ $good_urls = $chinfo['url']; }
}

四、PHP安全编程

1 安全配置

配置都在php.ini

2 SQL注入

// 1.addslashes
addslashes($str);

// 2.参数化查询
$sql = "SELECT HPhone, HName FROM host WHERE HNo = (SELECT UID FROM user WHERE UUsername = :username)";
$res = $db->prepare($sql);
$res->bindParam(':username', $_SESSION['username']);
$res->execute();

3 跨站脚本

# 1.htmlspecialchars,将下列实体进行转化:<,>,&,",'
htmlspecialchars($str);

# 2.自定义(网上下载的)
<?php
//RemoveXss函数主要用于跨站脚本的过滤
//Remove the exploer'bug XSS
function remove_xss($val) {
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
// this prevents some character re-spacing such as <java\0script>
// note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
$val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);
// straight replacements, the user should never need these since they're normal characters
// this prevents like <IMG SRC=@avascript:alert('XSS')>
$search = 'abcdefghijklmnopqrstuvwxyz';
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$search .= '1234567890!@#$%^&*()';
$search .= '~`";:?+/={}[]-_|\'\\';
for ($i = 0; $i < strlen($search); $i++) {
// ;? matches the ;, which is optional
// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
// @ @ search for the hex values
$val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
// @ @ 0{0,7} matches '0' zero to seven times
$val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
}
// now the only remaining whitespace attacks are \t, \n, and \r
$ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
$ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
$ra = array_merge($ra1, $ra2);
$found = true; // keep replacing as long as the previous round replaced something
while ($found == true) {
$val_before = $val;
for ($i = 0; $i < sizeof($ra); $i++) {
$pattern = '/';
for ($j = 0; $j < strlen($ra[$i]); $j++) {
if ($j > 0) {
$pattern .= '(';
$pattern .= '(&#[xX]0{0,8}([9ab]);)';
$pattern .= '|';
$pattern .= '|(&#0{0,8}([9|10|13]);)';
$pattern .= ')*';
}
$pattern .= $ra[$i][$j];
}
$pattern .= '/i';
$replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
if ($val_before == $val) {
// no replacements were made, so exit the loop
$found = false;
}
}
}
return $val;
}
?>

4 身份认证

// 安全函数
crypt(str, [salt]); // hash加密(算法自己设置)
md5(str, [raw]); // md5(raw规定结果是十六进制还是二进制)
sha1(str, [raw]); // sha1
crc32(str); // crc32校验
uniqid(); // 根据微秒时间生成唯一ID
md5_file(filename); // 计算文件md5散列值
base64_encode(str); // base64编码
urlencode(str); // url解码
// 验证码生成
<?php
session_start(); // 开启session
$image = imagecreatetruecolor(100,30); // 1.创建黑色画布
$bgcolor = imagecolorallocate($image,255,255,255); // 2.定义背景颜色为白色
imagefill($image,0,0,$bgcolor); // 3.填充背景颜色
$content = join('',array_merge(range(0,9),range('a','z'),range('A','Z'))); // 4.1定义验证码内容
$captcha = ""; // 4.2创建一个变量存储产生的验证码数据,便于用户提交核对
for($i = 0;$i < 4;$i++) // 绘制四个字符
{
$fontsize = 10; // 字体大小
$fontcolor = imagecolorallocate($image,mt_rand(0,120),mt_rand(0,120),mt_rand(0,120)); // 字体颜色为随机值
$fontcontent = substr($content,mt_rand(0,strlen($content)),1); // 设置字体内容
$captcha .= $fontcontent;
$x = ($i * 100 / 4) + mt_rand(5,10); // 显示的坐标
$y = mt_rand(5,10);
imagestring($image,$fontsize,$x,$y,$fontcontent,$fontcolor); // 输出一个字符到画布
}
$_SESSION["captcha"] = $captcha; // 将验证码保存到session变量中
for($i = 0;$i < 200;$i++) // 4.3设置背景干扰元素
{
$pointcolor = imagecolorallocate($image,mt_rand(50,200),mt_rand(50,200),mt_rand(50,200));
imagesetpixel($image,mt_rand(1,99),mt_rand(1,29),$pointcolor);
}
for($i = 0;$i < 3;$i++) // 4.4设置干扰线
{
$linecolor = imagecolorallocate($image,mt_rand(50,200),mt_rand(50,200),mt_rand(50,200));
imageline($image,mt_rand(1,99),mt_rand(1,29),mt_rand(1,99),mt_rand(1,29),$linecolor);
}
header('content-type:image/png'); // 5.强制浏览器输出.png格式图片文件
imagepng($image); // 6.输出图片到浏览器
imagedestroy($image); // 7.销毁图片
?>

5 编程流程

// 1.头文件中文设置
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

// 2.开启session和时区,包含防跳墙
<?php
if (session_status() == PHP_SESSION_NONE)
{
session_start();
}
date_default_timezone_set('Asia/Shanghai');
include("wall.php");
?>

// 3.获得数据(注意XSS和SQL注入)
<?php
$target = addslashes(remove_xss($_POST['search_content']));
?>

// 4.连接数据库
<?php
$flag = 1;
try
{
$ip = "localhost";
$database = "mysystem";
$db_username = "root";
$db_password = "root";
$dsn="mysql:host=${ip};dbname=${database}";
$db=new PDO($dsn,$db_username,$db_password);
$db->query("set names utf8"); //设置字符编码
}
catch( PDOException $e)
{
$flag = 0;
}
?>

// 5.数据库操作
<?php
$sql = "SELECT * FROM user WHERE username = :username ";
$res = $db->prepare($sql);
$res->bindParam(':username', $username);
$res->execute();
$row = $res->fetch(PDO::FETCH_ASSOC);
if($row > 0) {$row['username']}
else {echo 'error!';}
?>

// 6.直接显示后续页面或返回页面(返回的页面可用于AJAX请求操作)
<?php echo json_encode(array("count" => $count, "rows" => $rows)); ?>

五、PHP技巧

1 显示中文

任选一种:

html方式:<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

数据包方式:`<?php header('Content-type:text/html;charset=utf-8'); ?>


六、PHP框架

1 ThinkPHP8

序言 - ThinkPHP官方手册